/**
 * 
 */
package com.ubo.transform.java;

import com.ubo.java.model.EModifier;
import com.ubo.java.model.JavaModel;
import com.ubo.java.model.PackageModel;
import com.ubo.java.model.classifier.ArrayType;
import com.ubo.java.model.classifier.ClassModel;
import com.ubo.java.model.classifier.EPrimitiveTypes;
import com.ubo.java.model.classifier.EnumClassifier;
import com.ubo.java.model.classifier.ExistingClassifier;
import com.ubo.java.model.classifier.IClassifier;
import com.ubo.java.model.classifier.Interface;
import com.ubo.java.model.comment.Comment;
import com.ubo.java.model.declaration.Attribut;
import com.ubo.java.model.declaration.Parameter;
import com.ubo.java.model.declaration.Variable;
import com.ubo.java.model.methode.Constructor;
import com.ubo.java.model.methode.Method;
import com.ubo.java.model.methode.Prototype;

/**
 * @author saludegu
 * 
 */
public class JavaGenerator extends AJavaVisitor<StringBuffer> {

	/**
	 * 
	 * Constructor
	 * 
	 */
	public JavaGenerator() {
	}

	/**
	 * @see com.ubo.transform.java.IJavaVisitor#generate(com.ubo.java.model.classifier.EPrimitiveTypes)
	 */
	@Override
	public void generate(EPrimitiveTypes ePrimitiveTypes) {
		StringBuffer buffer = new StringBuffer();
		buffer.append(ePrimitiveTypes.toString());
		addToStack(buffer);
	}

	/**
	 * @see com.ubo.transform.java.IJavaVisitor#generate(com.ubo.java.model.classifier.ExistingClassifier)
	 */
	@Override
	public void generate(ExistingClassifier existingClassifier) {
		StringBuffer buffer = new StringBuffer();
		buffer.append(existingClassifier.toString());
		addToStack(buffer);
	}

	/**
	 * @see com.ubo.transform.java.IJavaVisitor#generate(com.ubo.java.model.declaration.Attribut)
	 */
	@Override
	public void generate(Attribut attribut) {
		StringBuffer buffer = new StringBuffer("\t");
		attribut.getComment().generate(this);
		buffer.append(getValue());
		buffer.append("\t");
		if (attribut.getVisibility() != null)
			buffer.append(attribut.getVisibility().toString() + " ");
		if (attribut.getModifier() != null && attribut.getModifier().size() > 0) {
			for (EModifier modifier : attribut.getModifier())
				buffer.append(modifier.toString() + " ");
		}
		buffer.append(attribut.getType().toString() + " ");
		buffer.append(attribut.getName());
		addToStack(buffer);
	}

	/**
	 * @see com.ubo.transform.java.IJavaVisitor#generate(com.ubo.java.model.declaration.Variable)
	 */
	@Override
	public void generate(Variable variable) {
		StringBuffer buffer = new StringBuffer();
		if (variable.getModifier() != null && variable.getModifier().size() > 0) {
			for (EModifier modifier : variable.getModifier())
				buffer.append(modifier.toString() + " ");
		}
		buffer.append(variable.getType().toString() + " ");
		buffer.append(variable.getName());
		addToStack(buffer);
	}

	/**
	 * @see com.ubo.transform.java.IJavaVisitor#generate(com.ubo.java.model.declaration.Parameter)
	 */
	@Override
	public void generate(Parameter parameter) {
		StringBuffer buffer = new StringBuffer();
		if (parameter.getModifier() != null
				&& parameter.getModifier().size() > 0) {
			for (EModifier modifier : parameter.getModifier())
				buffer.append(modifier.toString() + " ");
		}
		buffer.append(parameter.getType().toString() + " ");
		buffer.append(parameter.getName());
		addToStack(buffer);
	}

	/**
	 * @see com.ubo.transform.java.IJavaVisitor#generate(com.ubo.java.model.methode.Constructor)
	 */
	@Override
	public void generate(Constructor constructor) {
		StringBuffer buffer = new StringBuffer("\n\t");
		constructor.getComment().generate(this);
		buffer.append(getValue());
		buffer.append("\t");
		buffer.append(constructor.getVisibility().toString() + " ");
		buffer.append(constructor.getType().toString() + "(");
		if (constructor.getParameterList() != null
				&& constructor.getParameterList().size() > 0) {
			for (Parameter parameter : constructor.getParameterList()) {
				parameter.generate(this);
				buffer.append(getValue() + ",");
			}
			buffer.deleteCharAt(buffer.length() - 1);
		}
		buffer.append(") {\n\n\n\t}\n");
		addToStack(buffer);
	}

	/**
	 * @see com.ubo.transform.java.IJavaVisitor#generate(com.ubo.java.model.methode.Prototype)
	 */
	@Override
	public void generate(Prototype prototype) {
		StringBuffer buffer = new StringBuffer("\n\t");
		prototype.getComment().generate(this);
		buffer.append(getValue());
		buffer.append("\t");
		buffer.append(prototype.getVisibility().toString() + " ");
		if (prototype.getModifierList() != null
				&& prototype.getModifierList().size() > 0) {
			for (EModifier modifier : prototype.getModifierList())
				buffer.append(modifier.toString() + " ");
		}
		buffer.append(prototype.getType().toString() + " ");
		buffer.append(prototype.getName() + "(");
		if (prototype.getParameterList() != null
				&& prototype.getParameterList().size() > 0) {
			for (Parameter parameter : prototype.getParameterList()) {
				parameter.generate(this);
				buffer.append(getValue() + ",");
			}
			buffer.deleteCharAt(buffer.length() - 1);
		}
		buffer.append(")");
		if (prototype.getListClassThrowns() != null
				&& prototype.getListClassThrowns().size() > 0) {
			buffer.append(" throws ");
			for (ClassModel excep : prototype.getListClassThrowns())
				buffer.append(excep.printPath() + ",");
			buffer.deleteCharAt(buffer.length() - 1);
		}
		addToStack(buffer);
	}

	/**
	 * @see com.ubo.transform.java.IJavaVisitor#generate(com.ubo.java.model.methode.Method)
	 */
	@Override
	public void generate(Method signature) {
		StringBuffer buffer = new StringBuffer("\n\t");
		signature.getComment().generate(this);
		buffer.append(getValue());
		buffer.append("\t");
		if (signature.isOverrided())
			buffer.append("@Override\n\t");
		buffer.append(signature.getVisibility().toString() + " ");
		if (signature.getModifierList() != null
				&& signature.getModifierList().size() > 0)
			for (EModifier modifier : signature.getModifierList())
				buffer.append(modifier.toString() + " ");
		buffer.append(" " + signature.getType().toString() + " ");
		buffer.append(signature.getMethodName() + "(");
		if (signature.getParameterList() != null
				&& signature.getParameterList().size() > 0) {
			for (Parameter parameter : signature.getParameterList()) {
				parameter.generate(this);
				buffer.append(getValue() + ",");
			}
			buffer.deleteCharAt(buffer.length() - 1);
		}
		buffer.append(")");
		if (signature.getListClassThrowns() != null
				&& signature.getListClassThrowns().size() > 0) {
			buffer.append(" throws ");
			for (ClassModel excep : signature.getListClassThrowns())
				buffer.append(excep.printPath() + ",");
			buffer.deleteCharAt(buffer.length() - 1);
		}
		buffer.append(" {\n\t\t//TODO AUTO GENERATED METHOD.\n\t\treturn null;\n\t}");
		addToStack(buffer);
	}

	/**
	 * @see com.ubo.transform.java.IJavaVisitor#generate(com.ubo.java.model.PackageModel)
	 */
	@Override
	public void generate(PackageModel packageModel) {
		StringBuffer buffer = new StringBuffer();
		buffer.append(packageModel.printPath());
		addToStack(buffer);
	}

	/**
	 * 
	 * @see com.ubo.transform.java.IJavaVisitor#generate(com.ubo.java.model.classifier.ClassModel)
	 */
	@Override
	public void generate(ClassModel classModel) {
		StringBuffer buffer = new StringBuffer();
		buffer.append("package " + classModel.getPackage().printPath()
				+ ";\n\n\n");
		classModel.getComment().generate(this);
		buffer.append(getValue());
		buffer.append(classModel.getVisibility().toString() + " class "
				+ classModel.getClassifierName());
		// Generation de la classe étendue.
		if (classModel.getExtendedClasse() != null)
			buffer.append(" extends "
					+ classModel.getExtendedClasse().printPath());
		// Generation des interfaces implémentées.
		if (classModel.getInterfaceImplemented() != null) {
			buffer.append(" implements ");
			for (Interface inter : classModel.getInterfaceImplemented()) {
				buffer.append(inter.printPath() + ",");
			}
			buffer.deleteCharAt(buffer.length() - 1);
		}
		buffer.append(" {\n\n");
		// Generation des attributs de la classe.
		if (classModel.getAttributSet() != null
				&& classModel.getAttributSet().size() > 0) {
			for (Attribut attr : classModel.getAttributSet()) {
				attr.generate(this);
				buffer.append(getValue() + ";\n");
			}
		}
		// Generation du(des) constructeur(s).
		for (Constructor constructor : classModel.getConstructors()) {
			constructor.generate(this);
			buffer.append(getValue());
		}
		// Generation du(des) prototype(s), i.e. classes abstraites...
		if (classModel.getPrototypes() != null
				&& classModel.getPrototypes().size() > 0) {
			for (Prototype proto : classModel.getPrototypes()) {
				proto.generate(this);
				buffer.append(getValue() + ";\n");
			}
		}
		if (classModel.getMethodeSet() != null
				&& classModel.getMethodeSet().size() > 0) {
			for (Method meth : classModel.getMethodeSet()) {
				meth.generate(this);
				buffer.append(getValue() + "\n");
			}
		}
		buffer.append("\n}");
		addToStack(buffer);
	}

	/**
	 * @see com.ubo.transform.java.IJavaVisitor#generate(com.ubo.java.model.classifier.EnumClassifier)
	 */
	@Override
	public void generate(EnumClassifier enumClassifier) {
		StringBuffer buffer = new StringBuffer();
		buffer.append("package " + enumClassifier.getPackage().printPath()
				+ ";\n\n\n");
		enumClassifier.getComment().generate(this);
		buffer.append(getValue());
		buffer.append(enumClassifier.getVisibility().toString() + " enum "
				+ enumClassifier.getClassifierName());
		if (enumClassifier.getInterfaceImplemented() != null
				&& enumClassifier.getInterfaceImplemented().size() > 0) {
			buffer.append(" implements ");
			for (Interface inter : enumClassifier.getInterfaceImplemented())
				buffer.append(inter.printPath() + ",");
			buffer.deleteCharAt(buffer.length() - 1);
		}
		buffer.append("{");
		for (String str : enumClassifier.getValues()) {
			buffer.append(str.toUpperCase() + ",");
		}
		buffer.deleteCharAt(buffer.length() - 1);
		if (enumClassifier.getMethods() != null
				&& enumClassifier.getMethods().size() > 0) {
			buffer.append(";\n\n");
			for (Method method : enumClassifier.getMethods()) {
				method.generate(this);
				buffer.append(getValue());
			}
		}
		buffer.append("}");
		addToStack(buffer);
	}

	/**
	 * @see com.ubo.transform.java.IJavaVisitor#generate(com.ubo.java.model.classifier.Interface)
	 */
	@Override
	public void generate(Interface inter) {
		StringBuffer buffer = new StringBuffer();
		buffer.append("package " + inter.getPackage().printPath() + ";\n\n\n");
		inter.getComment().generate(this);
		buffer.append(getValue());
		buffer.append(inter.getVisibility().toString() + " interface "
				+ inter.getClassifierName());
		// Ajout des interfaces potentiellement étendues.
		if (inter.getInterfaceImplemented() != null
				&& inter.getInterfaceImplemented().size() > 0) {
			buffer.append(" extends ");
			for (Interface inte : inter.getInterfaceImplemented())
				buffer.append(inte.printPath() + ",");
			buffer.deleteCharAt(buffer.length() - 1);
		}
		buffer.append(" {\n\n");
		// Ajout des attributs
		if (inter.getAttributs() != null && inter.getAttributs().size() > 0) {
			for (Attribut attr : inter.getAttributs()) {
				attr.generate(this);
				buffer.append(getValue() + "; \n");
			}
		}
		// Ajout des prototypes
		if (inter.getPrototypes() != null && inter.getPrototypes().size() > 0) {
			for (Prototype proto : inter.getPrototypes()) {
				buffer.append("\t");
				proto.generate(this);
				buffer.append(getValue() + ";\n");

			}
		}
		buffer.append("\n}");
		addToStack(buffer);
	}

	/**
	 * @see com.ubo.transform.java.IJavaVisitor#generate(com.ubo.java.model.classifier.ArrayType)
	 */
	@Override
	public void generate(ArrayType arrayType) {
		StringBuffer strBuffer = new StringBuffer();
		// Ecriture de l'arrayType.
		strBuffer.append(arrayType.getType().toString() + "["
				+ arrayType.getSize() + "]");
		addToStack(strBuffer);
	}

	/**
	 * @see com.ubo.transform.java.IJavaVisitor#generate(com.ubo.java.model.comment.Comment)
	 */
	@Override
	public void generate(Comment comment) {
		StringBuffer buffer = new StringBuffer();
		buffer.append("/**\n");
		if (comment.getDescription() != null)
			buffer.append(comment.getDescription());
		if (comment.getParameters() != null
				&& comment.getParameters().size() > 0) {
			for (String param : comment.getParameters()) {
				buffer.append(param + "\t");
			}
		}
		if (comment.getSee() != null)
			buffer.append(comment.getSee());
		if (comment.getExceptions() != null
				&& comment.getExceptions().size() > 0) {
			for (String excep : comment.getExceptions()) {
				buffer.append(excep + "\t");
			}
		}
		if (comment.getAuthor() != null)
			buffer.append(comment.getAuthor());
		buffer.append("*/\n");
		addToStack(buffer);
	}

	/**
	 * @see com.ubo.transform.java.IJavaVisitor#generate(com.ubo.java.model.JavaModel)
	 */
	@Override
	public void generate(JavaModel javaModel) {
		StringBuffer buffer = new StringBuffer();
		for (IClassifier classifier : javaModel.getClassifiers()) {
			classifier.generate(this);
			buffer.append(getFromStack().toString());
		}
		addToStack(buffer);
	}
}
